import pygame
import random
import os

# 初始化Pygame
pygame.init()

# 游戏窗口设置
SCREEN_WIDTH = 480
SCREEN_HEIGHT = 720
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("羊了个羊")

# 颜色定义
BG_COLOR = (255, 255, 255)

# 卡片尺寸和间距
CARD_WIDTH = 55
CARD_HEIGHT = 70
SPACING = 30
LAYER_OFFSET = 5  # 每层卡片的偏移量

# 游戏区域布局
GRID_ROWS = 4
GRID_COLS = 4
grid_width = GRID_COLS * (CARD_WIDTH + SPACING) - SPACING
GRID_LEFT = (SCREEN_WIDTH - grid_width) // 2
GRID_TOP = 100

# 槽位区域设置
SLOT_ROWS = 1
SLOT_COLS = 7  # 最多存放7个卡片
slot_width = SLOT_COLS * (CARD_WIDTH + 5) - 5
SLOT_LEFT = (SCREEN_WIDTH - slot_width) // 2
SLOT_TOP = SCREEN_HEIGHT - CARD_HEIGHT - 50
SLOT_HEIGHT = CARD_HEIGHT + 20

# 撤销按钮设置
UNDO_MAX_TIMES = 3
undo_times = UNDO_MAX_TIMES
# 加载撤销按钮图片
try:
    image_folder = os.path.join(os.path.dirname(__file__), "image")
    undo_button_path = os.path.join(image_folder, "tile8.png")
    undo_button_img = pygame.image.load(undo_button_path)
    UNDO_BUTTON_WIDTH = undo_button_img.get_width()
    UNDO_BUTTON_HEIGHT = undo_button_img.get_height()
    UNDO_BUTTON_LEFT = 20
    UNDO_BUTTON_TOP = 20
    print("撤销按钮图片加载成功")
except Exception as e:
    print(f"撤销按钮图片加载失败: {e}")
    UNDO_BUTTON_WIDTH = 100
    UNDO_BUTTON_HEIGHT = 50
    UNDO_BUTTON_LEFT = 20
    UNDO_BUTTON_TOP = 20
    undo_button_img = None

# 加载背景图像
try:
    image_folder = os.path.join(os.path.dirname(__file__), "image")
    background_path = os.path.join(image_folder, "back.png")
    background_img = pygame.image.load(background_path)
    background_img = pygame.transform.scale(background_img, (SCREEN_WIDTH, SCREEN_HEIGHT))
    print("主背景图像加载成功")
except Exception as e:
    print(f"主背景图像加载失败: {e}")
    background_img = None

# 加载槽位背景图像
try:
    slot_bg_path = os.path.join(image_folder, "back2.png")
    slot_bg_img = pygame.image.load(slot_bg_path)
    slot_bg_img = pygame.transform.scale(slot_bg_img, (slot_width + 20, SLOT_HEIGHT + 20))
    print("槽位背景图像加载成功")
except Exception as e:
    print(f"槽位背景图像加载失败: {e}")
    slot_bg_img = None

# 加载卡片图片
card_images = []
try:
    for i in range(5):
        if i == 0:
            tile_path = os.path.join(image_folder, "tile.png")
        else:
            tile_path = os.path.join(image_folder, f"tile{i}.png")

        if os.path.exists(tile_path):
            img = pygame.image.load(tile_path)
            img = pygame.transform.scale(img, (CARD_WIDTH, CARD_HEIGHT))
            card_images.append(img)
            print(f"卡片图片 {os.path.basename(tile_path)} 加载成功")
        else:
            print(f"卡片图片 {tile_path} 不存在")

    if not card_images:
        raise Exception("没有找到任何卡片图片")

except Exception as e:
    print(f"卡片图片加载失败: {e}")
    COLORS = [
        (255, 0, 0),  # 红
        (0, 255, 0),  # 绿
        (0, 0, 255),  # 蓝
        (255, 255, 0),  # 黄
        (128, 0, 128),  # 紫
    ]

# 游戏状态
slots = []
score = 0
game_over = False
game_won = False
undo_stack = []
# 移动中的卡片信息
moving_card = None
move_steps = 0
MOVE_TOTAL_STEPS = 30  # 总移动步数，可调整以控制移动速度

def check_victory():
    """检查是否胜利"""
    for row in grid:
        for stack in row:
            if len(stack) > 0:
                return False
    return len(slots) == 0

# 初始化卡片堆
grid = []
for row in range(GRID_ROWS):
    grid_row = []
    for col in range(GRID_COLS):
        layers = random.randint(3, 5)
        max_card_type = len(card_images) - 1 if card_images else len(COLORS) - 1
        stack = [(random.randint(0, max_card_type), layer) for layer in range(layers)]
        stack += [stack[-1]] * (3 - layers % 3) if layers % 3 != 0 else []
        grid_row.append(stack)
    grid.append(grid_row)

# 主循环
clock = pygame.time.Clock()
running = True

while running:
    # 事件处理
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        elif event.type == pygame.MOUSEBUTTONDOWN and not game_over:
            x, y = pygame.mouse.get_pos()
            # 检查是否点击了撤销按钮
            if (
                UNDO_BUTTON_LEFT <= x <= UNDO_BUTTON_LEFT + UNDO_BUTTON_WIDTH
                and UNDO_BUTTON_TOP <= y <= UNDO_BUTTON_TOP + UNDO_BUTTON_HEIGHT
                and undo_times > 0
            ):
                if undo_stack:
                    prev_grid, prev_slots, prev_score = undo_stack.pop()
                    grid[:] = [row[:] for row in prev_grid]
                    slots[:] = prev_slots[:]
                    score = prev_score
                    undo_times -= 1
            else:
                # 记录当前状态用于撤销
                undo_stack.append(([row[:] for row in grid], slots[:], score))
                # 计算点击位置
                for row in range(GRID_ROWS):
                    for col in range(GRID_COLS):
                        if len(grid[row][col]) > 0:
                            card_x = GRID_LEFT + col * (CARD_WIDTH + SPACING)
                            card_y = GRID_TOP + row * (CARD_HEIGHT + SPACING)
                            top_card_layer = grid[row][col][-1][1]
                            for layer, (card_type, card_layer) in enumerate(grid[row][col]):
                                card_y_offset = card_y - (top_card_layer - card_layer) * LAYER_OFFSET
                                if (
                                    card_x <= x <= card_x + CARD_WIDTH
                                    and card_y_offset <= y <= card_y_offset + CARD_HEIGHT
                                    and layer == len(grid[row][col]) - 1
                                ):
                                    # 检查槽位是否已满（改为7块）
                                    if len(slots) >= SLOT_COLS:  # SLOT_COLS = 7
                                        game_over = True
                                        continue

                                    # 取出顶层卡片
                                    card = grid[row][col].pop()[0]
                                    target_x = SLOT_LEFT + len(slots) * (CARD_WIDTH + 5)
                                    target_y = SLOT_TOP
                                    moving_card = (card, card_x, card_y_offset, target_x, target_y)
                                    move_steps = 0
                                    slots.append(card)

                                    # 检查连续三个相同卡片
                                    if len(slots) >= 3 and slots[-1] == slots[-2] == slots[-3]:
                                        del slots[-3:]
                                        score += 1

                                    # 再次检查槽位是否已满
                                    if len(slots) >= SLOT_COLS:
                                        game_over = True

                                    # 检查胜利条件
                                    if check_victory():
                                        game_won = True
                                        game_over = True

    # 处理移动中的卡片
    if moving_card and move_steps < MOVE_TOTAL_STEPS:
        card, start_x, start_y, target_x, target_y = moving_card
        current_x = start_x + (target_x - start_x) * move_steps / MOVE_TOTAL_STEPS
        current_y = start_y + (target_y - start_y) * move_steps / MOVE_TOTAL_STEPS
        move_steps += 1
    elif moving_card:
        moving_card = None

    # 绘制界面
    if background_img:
        screen.blit(background_img, (0, 0))
    else:
        screen.fill(BG_COLOR)

    # 绘制卡片堆
    for row in range(GRID_ROWS):
        for col in range(GRID_COLS):
            x = GRID_LEFT + col * (CARD_WIDTH + SPACING)
            y = GRID_TOP + row * (CARD_HEIGHT + SPACING)
            if len(grid[row][col]) > 0:
                top_card_layer = grid[row][col][-1][1]
                for card_type, card_layer in grid[row][col]:
                    y_offset = y - (top_card_layer - card_layer) * LAYER_OFFSET
                    if card_images:
                        screen.blit(card_images[card_type], (x, y_offset))
                    else:
                        pygame.draw.rect(screen, COLORS[card_type], (x, y_offset, CARD_WIDTH, CARD_HEIGHT))

    # 绘制槽位背景
    if slot_bg_img:
        screen.blit(slot_bg_img, (SLOT_LEFT - 10, SLOT_TOP - 10))
    else:
        pygame.draw.rect(screen, (200, 200, 200),
                         (SLOT_LEFT - 5, SLOT_TOP - 5,
                          slot_width + 10, SLOT_HEIGHT + 10),
                         border_radius=10)

    # 绘制槽位中的卡片
    for i, card in enumerate(slots):
        x = SLOT_LEFT + i * (CARD_WIDTH + 5)
        if card_images:
            screen.blit(card_images[card], (x, SLOT_TOP))
        else:
            pygame.draw.rect(screen, COLORS[card], (x, SLOT_TOP, CARD_WIDTH, CARD_HEIGHT))

    # 绘制移动中的卡片
    if moving_card:
        card, current_x, current_y, _, _ = moving_card
        if card_images:
            screen.blit(card_images[card], (current_x, current_y))
        else:
            pygame.draw.rect(screen, COLORS[card], (current_x, current_y, CARD_WIDTH, CARD_HEIGHT))

    # 绘制状态信息
    font = pygame.font.Font(None, 36)
    text = font.render(f"Score: {score}", True, (0, 0, 0))
    screen.blit(text, (20, 20 + UNDO_BUTTON_HEIGHT + 10))

    # 绘制槽位容量提示
    capacity_text = font.render(f"{len(slots)}/{SLOT_COLS}", True, (100, 100, 100))
    screen.blit(capacity_text, (SCREEN_WIDTH - 60, 20))

    # 绘制撤销按钮
    if undo_button_img:
        screen.blit(undo_button_img, (UNDO_BUTTON_LEFT, UNDO_BUTTON_TOP))
    else:
        pygame.draw.rect(screen, (200, 0, 0), (UNDO_BUTTON_LEFT, UNDO_BUTTON_TOP, UNDO_BUTTON_WIDTH, UNDO_BUTTON_HEIGHT))
        undo_text = font.render(f"Undo ({undo_times})", True, (255, 255, 255))
        screen.blit(undo_text, (UNDO_BUTTON_LEFT + 10, UNDO_BUTTON_TOP + 10))

    if game_over:
        text = font.render("YOU WIN!" if game_won else "GAME OVER!",
                           True, (0, 255, 0) if game_won else (255, 0, 0))
        screen.blit(text, (SCREEN_WIDTH // 2 - 80, SCREEN_HEIGHT // 2 - 20))

    pygame.display.flip()
    clock.tick(30)

pygame.quit()